From 072186cf673d593478aced4614be65d19f459818 Mon Sep 17 00:00:00 2001 From: Gianni Tedesco Date: Wed, 4 Aug 2010 14:43:46 +0100 Subject: [PATCH] xl: detect pci-insert-failed dm status on pci-passthrough NOTE: This functionality depends on a corresponding qemu-dm patch to work as expected. Should be safe to use with an un-patched qemu-dm as before. libxl_wait_for_device_model can only wait for one status value, re-work the API so that a callback function can chose between several different possible status values for qemu-dm and fix up all callers appropriately. In the case of PCI device insert we succeed if qemu-dm reports "pci-device-inserted" and error out instead of hanging forever if it fails since qemu-dm now reports a status of "pci-insert-failed". Signed-off-by: Gianni Tedesco Signed-off-by: Stefano Stabellini --- tools/libxl/libxl.c | 10 +++++----- tools/libxl/libxl_device.c | 26 +++++++++++++++++--------- tools/libxl/libxl_internal.h | 2 ++ tools/libxl/libxl_pci.c | 24 +++++++++++++++++++++--- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 0a2dbf89e9..b34806411e 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -1420,12 +1420,12 @@ int libxl_detach_device_model(libxl_ctx *ctx, int libxl_confirm_device_model_startup(libxl_ctx *ctx, libxl_device_model_starting *starting) { - int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", - libxl_spawn_check, - starting->for_spawn); - int detach = libxl_detach_device_model(ctx, starting); + int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", NULL, NULL); + int detach; + if ( !problem ) + problem = libxl_spawn_check(ctx, starting->for_spawn); + detach = libxl_detach_device_model(ctx, starting); return problem ? problem : detach; - return 0; } diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index c59c631457..c81b85475b 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -380,6 +380,8 @@ int libxl_device_del(libxl_ctx *ctx, libxl_device *dev, int wait) int libxl_wait_for_device_model(libxl_ctx *ctx, uint32_t domid, char *state, int (*check_callback)(libxl_ctx *ctx, + uint32_t domid, + const char *state, void *userdata), void *check_callback_userdata) { @@ -402,18 +404,24 @@ int libxl_wait_for_device_model(libxl_ctx *ctx, nfds = xs_fileno(xsh) + 1; while (rc > 0 || (!rc && tv.tv_sec > 0)) { p = xs_read(xsh, XBT_NULL, path, &len); - if (p && (!state || !strcmp(state, p))) { - free(p); - xs_unwatch(xsh, path, path); - xs_daemon_close(xsh); - if (check_callback) { - rc = check_callback(ctx, check_callback_userdata); - if (rc) return rc; - } - return 0; + if ( NULL == p ) + goto again; + + if ( NULL != state && strcmp(p, state) ) + goto again; + + if ( NULL != check_callback ) { + rc = (*check_callback)(ctx, domid, p, check_callback_userdata); + if ( rc > 0 ) + goto again; } + free(p); + xs_unwatch(xsh, path, path); + xs_daemon_close(xsh); + return rc; again: + free(p); FD_ZERO(&rfds); FD_SET(xs_fileno(xsh), &rfds); rc = select(nfds, &rfds, NULL, NULL, &tv); diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 36a2829f97..3f0454468a 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -162,6 +162,8 @@ int libxl_devices_destroy(libxl_ctx *ctx, uint32_t domid, int force); int libxl_wait_for_device_model(libxl_ctx *ctx, uint32_t domid, char *state, int (*check_callback)(libxl_ctx *ctx, + uint32_t domid, + const char *state, void *userdata), void *check_callback_userdata); int libxl_wait_for_backend(libxl_ctx *ctx, char *be_path, char *state); diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c index 20f4a00218..c4dc0e4146 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -531,6 +531,20 @@ int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, in return 0; } +static int pci_ins_check(libxl_ctx *ctx, uint32_t domid, const char *state, void *priv) +{ + char *orig_state = priv; + + if ( !strcmp(state, "pci-insert-failed") ) + return -1; + if ( !strcmp(state, "pci-inserted") ) + return 0; + if ( !strcmp(state, orig_state) ) + return 1; + + return 1; +} + static int do_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) { char *path; @@ -553,13 +567,17 @@ static int do_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) pcidev->bus, pcidev->dev, pcidev->func); path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid); xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins")); - if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, NULL) < 0) - XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time"); + rc = libxl_wait_for_device_model(ctx, domid, NULL, pci_ins_check, state); path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid); vdevfn = libxl_xs_read(ctx, XBT_NULL, path); - sscanf(vdevfn + 2, "%x", &pcidev->vdevfn); path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); + if ( rc < 0 ) + XL_LOG(ctx, XL_LOG_ERROR, "qemu refused to add device: %s", vdevfn); + else if ( sscanf(vdevfn, "0x%x", &pcidev->vdevfn) != 1 ) + rc = -1; xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); + if ( rc ) + return ERROR_FAIL; } else { char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func); -- 2.30.2